package com.asm.test;

import com.dny.asmtop.*;
import com.dny.asmtop.op.CommandSequence;

import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.function.Predicate;

/**
 * Created by jlutt on 2018-01-19.
 *
 * @author jlutt
 */
public interface BeanConvertMap<T> {

  /**
   * 创建转换接口
   * @param srcClass 源对象类型
   * @param <T>
   * @return
   */
  static <T> BeanConvertMap<T> create(final Class<T> srcClass) {
    return create(srcClass, null);
  }

  /**
   * 创建转换接口
   *
   * @param srcClass       源对象类型
   * @param fieldPredicate 字段过滤条件
   * @param <T>
   * @return
   */
  @SuppressWarnings("unchecked")
  static <T> BeanConvertMap<T> create(final Class<T> srcClass, final Predicate<String> fieldPredicate) {
    BeanConvertMap<T> convert = ClassBuilder.create(ASMClassLoader.create(), BeanConvertMap.class)
        .addMethod("apply", ((WithValue<Command>) () -> {
          CommandSequence sequence = CommandSequence.create();
          for (java.lang.reflect.Method getter : srcClass.getMethods()) {
            String col = "";
            //region 查找字段名，查找条件：有get和set方法的字段
            if (Modifier.isStatic(getter.getModifiers()))
              continue;
            if (getter.getParameterTypes().length > 0)
              continue;
            if ("getClass".equals(getter.getName()))
              continue;
            if (!getter.getName().startsWith("get") && !getter.getName().startsWith("is"))
              continue;
            java.lang.reflect.Method setter;
            boolean is = getter.getName().startsWith("is");

            try {
              setter = srcClass.getMethod(getter.getName().replaceFirst(is ? "is" : "get", "set"), getter.getReturnType());
              col = setter.getName().substring(3);
              if (col.length() < 2 || Character.isLowerCase(col.charAt(1))) {
                char[] cs = col.toCharArray();
                cs[0] = Character.toLowerCase(cs[0]);
                col = new String(cs);
              }
              if (fieldPredicate != null) {
                if (!fieldPredicate.test(col))
                  continue;
              }
            } catch (Exception e) {
              continue;
            }

            if ("".equals(col))
              continue;
            //endregion

            sequence.add(CB.call(
                //map中是泛型，所以需要把key和value转换为object进行处理，否则找不到put方法
                CB.arg(0),
                "put",
                CB.cast(CB.value(col), Object.class),
                CB.cast(CB.field(CB.cast(CB.arg(1), srcClass), col), Object.class)
                )
            );

            //sequence.add(CB.voidReturn());
          }

          sequence.add(CB.arg(0));
          return sequence;
        }).get())
        .buildInstance();

    return convert;
  }

  Map<String, Object> apply(Map<String, Object> map, T src);
}
